package org.msn.client.handler;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.msn.rest.RestResult;
import org.msn.util.JsonUtil;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@Slf4j
public abstract class RequestHandler extends SimpleChannelInboundHandler<String> {
    public static ChannelHandlerContext ctx = null;

    private static final ByteBuf PING =
            Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("ping", CharsetUtil.UTF_8));

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
//        String message = msg;
//        if("ping".equals(message)) {
//            log.info(ctx.channel().remoteAddress() + "===>client: " + msg);
//        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
//        ctx.writeAndFlush(Unpooled.copiedBuffer("客户端启动", CharsetUtil.UTF_8));
        // 存放当前实例的句柄
        RequestHandler.ctx = ctx;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //接收服务端发送过来的消息
        log.info("收到服务端" + ctx.channel().remoteAddress() + "的消息：" + msg);
        //解析数据
        parse(ctx, JsonUtil.formJson(msg, RestResult.class));
    }

//    /**
//     * 四秒没有收到写请求 向服务器发心跳数据
//     * @param ctx
//     * @param evt
//     * @throws Exception
//     */
//    @Override
//    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
//        if(evt instanceof IdleStateEvent) {
//            IdleStateEvent event = (IdleStateEvent) evt;
//            if(IdleState.WRITER_IDLE.equals(event.state())) {
//                ctx.writeAndFlush(PING.duplicate()).addListener(ChannelFutureListener.CLOSE_ON_FAILURE) ;
//            }
//        }
//        super.userEventTriggered(ctx, evt);
//    }

    /**
     * 解析请求调用相应的方法
     *
     * @param ctx
     * @param restResult
     */
    public void parse(ChannelHandlerContext ctx, RestResult restResult) {
        try {
            getMethodByMethodName(restResult.getMsg()).invoke(this, ctx, restResult.getData());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    private Method getMethodByMethodName(String methodName) throws NoSuchMethodException {
        return getClass().getDeclaredMethod(methodName, ChannelHandlerContext.class, Object.class);
    }

    protected abstract void sendMsg(ChannelHandlerContext ctx, Object data);
    protected abstract void getAllRoom(ChannelHandlerContext ctx, Object data);
    protected abstract void successJoinRoom(ChannelHandlerContext ctx, Object data);
    protected abstract void failJoinRoom(ChannelHandlerContext ctx, Object data);
    protected abstract void getRoomAllUserIP(ChannelHandlerContext ctx, Object data);
    protected abstract void openVideo(ChannelHandlerContext ctx, Object data);
    protected abstract void openSound(ChannelHandlerContext ctx, Object data);

    protected abstract void sendCreateRoom(ChannelHandlerContext ctx, Object data);
    protected abstract void sendGetAllRoom(ChannelHandlerContext ctx, Object data);
    protected abstract void sendSendMsg(ChannelHandlerContext ctx, Object data);
    protected abstract void sendLeaveRoom(ChannelHandlerContext ctx, Object data);
    protected abstract void sendJoinRoom(ChannelHandlerContext ctx, Object data);
    protected abstract void sendGetRoomAllUserIP(ChannelHandlerContext ctx, Object data);
    protected abstract void sendOpenVideo(ChannelHandlerContext ctx, Object data);
    protected abstract void sendOpenSound(ChannelHandlerContext ctx, Object data);

}
